home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 March / Macworld (1998-03) (Disk 1).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / Menus / eudoraMenu.tcl < prev    next >
Encoding:
Text File  |  1997-12-08  |  22.6 KB  |  854 lines  |  [TEXT/ALFA]

  1. #     <nowrap>
  2. # Built for Eudora
  3.  
  4. # Class message: A message
  5. # Elements:
  6. #     field by name
  7. # Properties:
  8. #     body  string  -- the body of the message
  9. #     priority  integer  -- the priority
  10. #     label  integer  -- the index of the label
  11. #     status  unread/already read/replied/forwarded/redirected/not sendable/sendable/queued/sent/never sent  -- the message status
  12. #     sender  string  -- the sender as appearing in the message summary
  13. #     date  string  [r/o]  -- the date as appearing in the message summary
  14. #     subject  string  -- the subject as appearing in the message summary
  15. #     size  integer  [r/o]  -- the size of the message
  16. #     outgoing  boolean  [r/o]  -- is the message is outgoing?
  17. #     signature  none/standard/alternate  -- which signature the message should have
  18. #     QP  boolean  -- is Eudora allowed to encode text?
  19. #     return receipt  boolean  -- is a return receipt is requested?
  20. #     wrap  boolean  -- should the text be wrapped when sent?
  21. #     tab expansion  boolean  -- should tabs get expanded to spaces?
  22. #     keep copy  boolean  -- should a copy should be kept after message is sent?
  23. #     preserve macintosh info  boolean  -- should Macintosh information always be sent with attachments?
  24. #     attachment encoding  AppleDouble/AppleSingle/BinHex/uuencode  -- the type of encoding to use for attachments
  25. #     show all headers  boolean  -- should all headers be visible?
  26. #     transliteration table  integer  -- the resource id of the transliteration table
  27. #     will be fetched  boolean  -- will the message be [re]fetched on next check?
  28. #     will be deleted  boolean  -- will the message be deleted from server on next check?
  29.  
  30. alpha::menu eudoraMenu 0.1 "•138" in_menu {
  31.     addMode Mail dummyMail {} eudoraMenu
  32.     set unixMode(rmail) {Mail}
  33. } uninstall {this-file} help {file "Eudora"}
  34.  
  35. proc eudoraMenu {} {}
  36. proc dummyMail {} {}
  37.  
  38. if {![info exists trashName]} {set trashName "Trash"}
  39.  
  40. newPref v prefixString {> } Mail
  41. newPref v wordBreak {(\$)?[a-zA-Z0-9_.]+} Mail
  42. newPref f wordWrap {0} Mail
  43. newPref v wordBreakPreface {[^a-zA-Z0-9_\$]} Mail
  44. newPref f autoMark 0 Mail
  45. newPref file eudoraNicknames "" Mail
  46. newPref f tossOnQueue 1 Mail
  47. newPref f switchOnQueue 0 Mail
  48.  
  49. set mailKeywords {{Subject:} {To:} {From:} {Cc:} {Date:} {Sender:}}
  50. regModeKeywords -k blue -e {>} Mail $mailKeywords
  51.  
  52. bind '\t'                         mailTab Mail
  53.  
  54. #===============================================================================
  55. # Utility routines.
  56. proc eudoraFolder {} { nameObject euMF {'TEXT'()} [nullObject] }
  57. proc mailboxByName {name} { nameObject euMB "“$name”" [eudoraFolder] }
  58. proc mailboxByIndex {ind} { indexObject euMB $ind [eudoraFolder] }
  59. proc eudoraMessage {msg_id mailbox} { indexObject euMS $msg_id [mailboxByName $mailbox] }
  60. proc mailboxProperty {prop mailbox} { objectProperty 'CSOm' $prop [mailboxByName $mailbox] }
  61. proc messageProperty {prop msg_id mailbox} { objectProperty 'CSOm' $prop [eudoraMessage $msg_id $mailbox] }
  62.  
  63. # Get path-name for indicated mailbox
  64. proc mailboxPathName {name} {
  65.     extractPath [mailboxProperty euFS $name]
  66. }
  67.  
  68. proc mailboxPathIndex {ind} {
  69.     set res [objectProperty 'CSOm' euFS [mailboxByIndex $ind]]
  70.     return [extractPath $res]
  71. }
  72.  
  73. #===============================================================================
  74.  
  75.  
  76. proc checkMailPath {} {
  77.     set name [nameFromAppl CSOm]
  78.     launch $name
  79.     return [file tail $name]
  80. }
  81.  
  82. if {![info exists eudoraBoxes]} {
  83.     set eudoraBoxes {In Out}
  84. }
  85.  
  86. menu -n $eudoraMenu -p eudoraProc {
  87.     "<SbackgroundEudora"
  88.     "<Seudora"
  89.     "help"
  90.     "(-"
  91.     "/e<U<BnewMessage"
  92.     "cc"
  93.     "bcc"
  94.     "(-"
  95.     "/f<U<Bsend"
  96.     "/g<U<S<Breply"
  97.     "/g<U<I<S<BreplyToAll"
  98.     "(-"
  99.     "/,<SfinishNickname"
  100.     "/,<S<O<IsubstituteNickname"
  101.     "editNicknames"
  102.     "updateNicknames"
  103.     "(-"
  104.     "updateMailboxLists"
  105.     {menu -n open -p mailBoxProc -m {}}
  106.     {menu -n moveTo -p transferProc -m {}}
  107.     "(-"
  108.     {menu -n tellEudora -p eudoraProc {
  109.         "/k<UflushOutbox"
  110.         "/l<UcheckForMail"
  111.         "(-"
  112.         startNotifying
  113.         stopNotifying}}
  114.     {menu -n mailFlags -p mailFlagsProc {alertOnIncoming flushOnCheck immediateSend -- trashName}}
  115. }
  116. menu -n open -p mailBoxProc -m [concat [list "/h<U<BOpen Mailbox…" "(-"] $eudoraBoxes]
  117. menu -n moveTo -p transferProc -m [concat [list "/i<U<BMove To Trash" "/j<U<BMove To Mailbox…" "(-"] $eudoraBoxes]
  118.  
  119. if {$MailmodeVars(eudoraNicknames) == "" \
  120.     && [file exists "[file dirname [file dirname $PREFS]]:Eudora Folder:Eudora Nicknames"]} {
  121.     set MailmodeVars(eudoraNicknames) "[file dirname [file dirname $PREFS]]:Eudora Folder:Eudora Nicknames"
  122. }
  123.  
  124. proc updateNicknames {{arg ""}} {
  125.     global euNicknames eudoraNicknames
  126.     
  127.     if {![info exists eudoraNicknames] || ![file exists $eudoraNicknames]} {
  128.         if {![string length $arg]} {
  129.             alertnote {Please locate the file "Eudora Nicknames" using Mail mode's prefs.}
  130.         }
  131.         return
  132.     }
  133.     
  134.     set fd [open $eudoraNicknames]
  135.     foreach a [split [read $fd] "\n"] {
  136.         if {[llength $a]} {
  137.             set euNicknames([lindex $a 1]) [lindex $a 2]
  138.         }
  139.     }
  140.     close $fd
  141. }
  142. updateNicknames quiet
  143.  
  144.  
  145. proc finishNickname {} {
  146.     global euNicknames
  147.     set pos [getPos]
  148.     backwardWord
  149.     set text [getText [getPos] $pos]
  150.     goto $pos
  151.     foreach w [array names euNicknames] {
  152.         if {[string match "$text*" $w]} {
  153.             lappend matches $w
  154.         }
  155.     }
  156.     if {![llength $matches]} {
  157.         beep
  158.     } else {
  159.         insertText [string range [largestPrefix $matches] [string length $text] end]
  160.     }
  161. }    
  162.  
  163.  
  164. proc editNicknames {} {
  165.     global eudoraNicknames
  166.     
  167.     edit -w "$eudoraNicknames"
  168. }
  169.  
  170.  
  171. proc substituteNickname {} {
  172.     global euNicknames
  173.     finishNickname
  174.     set to [getPos]
  175.     backwardWord
  176.     set from [getPos]
  177.     set text [getText $from $to]
  178.     goto $to
  179.  
  180.     if {[info exists euNicknames($text)]} {
  181.         replaceText $from $to [set euNicknames($text)]
  182.     }
  183. }
  184.  
  185. proc openMailbox {} {
  186.     global eudoraBoxes eudoraLastFolder modifiedVars
  187.     if {[info exists eudoraLastFolder]} {
  188.         set fold $eudoraLastFolder
  189.     } else {
  190.         set fold [lindex $eudoraBoxes 0]
  191.     }
  192.     set eudoraLastFolder [sPromptChoices "Open mailbox" $fold $eudoraBoxes]
  193.     mailBoxProc dummy $eudoraLastFolder
  194.     lappend modifiedVars eudoraLastFolder
  195. }
  196.  
  197.  
  198. proc moveToFolderProc {curr c} {
  199.     global eudoraBoxes
  200.     if {$c != "\t"} {return $c}
  201.     
  202.     set matches {}
  203.     foreach w $eudoraBoxes {
  204.         if {[string match "$curr*" $w]} {
  205.             lappend matches $w
  206.         }
  207.     }
  208.     if {![llength $matches]} {
  209.         beep
  210.     } else {
  211.         return [string range [largestPrefix $matches] [string length $curr] end]
  212.     }
  213.     return ""
  214. }
  215.  
  216.  
  217. proc moveToMailbox {} {
  218.     global eudoraLastFolder modifiedVars trashName
  219.     
  220.     if {[info exists eudoraLastFolder]} {
  221.         set fold $eudoraLastFolder
  222.     } else {
  223.         set fold $trashName
  224.     }
  225.     
  226.     set folder [statusPrompt -f "Move to ($fold): " moveToFolderProc]
  227.     if {[string length $folder]} {
  228.         doFolderMove $folder
  229.         set eudoraLastFolder $folder
  230.         lappend modifiedVars eudoraLastFolder
  231.     } else {
  232.         doFolderMove $fold
  233.     }
  234. }
  235.  
  236.  
  237. proc eudoraProc {menu item} {
  238.     global HOME eudoraMenu
  239.  
  240.     switch $item {
  241.         "eudora"        {app::launchFore CSOm}
  242.         "backgroundEudora"        {launch [nameFromAppl CSOm]}
  243.         "help"            {edit -r "$HOME:Help:Eudora"}
  244.         "cc"            {eudoraCc}
  245.         "bcc"            {eudoraBcc}
  246.         "newMessage"    {mailNewMsg}
  247.         "reply"            {mailReplymsg}
  248.         "replyToAll"    {mailReplymsg 1}
  249.         "send"            {checkMailPath; mailSendCreatedMsg}
  250.         "flushOutbox"    {checkMailPath; mailFlushOut}
  251.         "checkForMail"    {checkMailPath; mailCheck}
  252.         "startNotifying" "checkMailPath; startNotifying"
  253.         "stopNotifying"    "checkMailPath; stopNotifying"
  254.         "moveToTrash"    {mailTrashmsg}
  255.         "Move To Trash"    {mailTrashmsg}
  256.         "Create New"    {eudoraNewMailbox}
  257.         "Delete"        {eudoraDeleteMailbox}
  258.         default            $item
  259.     }
  260. }
  261.  
  262. if {![info exists mailflushOnCheck]} {set mailflushOnCheck 1}
  263. if {![info exists mailalertOnIncoming]} {set mailalertOnIncoming 1}
  264. if {![info exists mailimmediateSend]} {set mailimmediateSend 0}
  265. markMenuItem mailFlags flushOnCheck $mailflushOnCheck
  266. markMenuItem mailFlags alertOnIncoming $mailalertOnIncoming
  267. markMenuItem mailFlags immediateSend $mailimmediateSend
  268.  
  269.  
  270. proc mailFlagsProc {menu flag} {
  271.     global mail$flag modifiedVars trashName
  272.  
  273.     if {$flag == "trashName"} {
  274.         set trashName [prompt "Trash folder name:" $trashName]
  275.         lappend modifiedVars trashName
  276.         return
  277.     }
  278.     
  279.  
  280.     set mail$flag [expr 1 - [set mail$flag]]
  281.     lappend modifiedVars mail$flag
  282.     markMenuItem mailFlags $flag [set mail$flag]
  283. }
  284.  
  285.  
  286. proc mailBoxProc {menu item} {
  287.     global inboxMembers ALPHA eudoraBoxes modifiedVars
  288.     global tileLeft tileTop tileHeight errorHeight defWidth
  289.  
  290.     if {$item == "Open Mailbox"} {
  291.         return [openMailbox]
  292.     }
  293.     
  294.     killMailboxWindow
  295.  
  296.     checkMailPath
  297.     switchTo $ALPHA
  298.  
  299.     global trashedMsgs$item
  300.     set trashedMsgs$item {}
  301.     
  302.     set inboxMembers {}
  303.     set text {}
  304.     set ind 1
  305.     foreach msg [mailSenders $item] {
  306.         set from [mailAddr [lindex $msg 0]]
  307.         set tag {}
  308.         while {[lsearch $inboxMembers $from$tag] >= 0} {
  309.             if {![string length $tag]} {
  310.                 set tag { <2>}
  311.             } else {
  312.                 regexp {[0-9]+} $tag tag
  313.                 set tag " <[expr $tag + 1]>"
  314.             }
  315.         }
  316.         append text [format "%-40s : %s\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$item∞$ind\r" "$from$tag" [lindex $msg 1]]
  317.         lappend inboxMembers $from$tag
  318.         incr ind
  319.     }
  320.     if {![string length $text]} {
  321.         alertnote "No messages in '$item'!"
  322.         return
  323.     }
  324.     
  325.     new -n "* MAILBOX '$item' *" -g $tileLeft $tileTop $defWidth $errorHeight -m Brws
  326.     insertText "(<cr> to go to message)\r-----\r$text"
  327.     
  328.     select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
  329.     setWinInfo dirty 0
  330.     setWinInfo read-only 1
  331.     message ""
  332. }
  333.  
  334. proc eudoraNewMailbox {} {
  335. }
  336.  
  337.  
  338. proc eudoraDeleteMailbox {} {
  339. }
  340.  
  341.  
  342. proc killMailboxWindow {} {
  343.     if {[set ind [lsearch [winNames] {*MAILBOX*}]] >= 0} {
  344.         set win [lindex [winNames] $ind]
  345.         bringToFront $win
  346.         killWindow
  347.     }
  348. }
  349.  
  350.  
  351. proc mailGotoMatch {} {
  352.     if {[regexp {∞(.+)∞([0-9]+)} [getText [lineStart [getPos]] [nextLineStart [getPos]]] dummy folder ind]} {
  353.         global trashedMsgs$folder
  354.         
  355.         set deleted 0
  356.         for {set i 1} {$i < $ind} {incr i} {
  357.             if {[lsearch [set trashedMsgs$folder] $i] >= 0} {
  358.                 incr deleted
  359.             }
  360.         }
  361.         mailOpen $folder [expr $ind - $deleted] $ind
  362.     }
  363. }
  364.  
  365.  
  366. proc mailAddr {name} {
  367.     if {![regexp {<(.*)>} $name dummy addr]} {
  368.         regexp {^[^ ]+} $name addr
  369.     }
  370.     return $addr
  371. }
  372.  
  373.  
  374. proc mailSenders {folder} {
  375.     set cnt [mailCountMsgs $folder]
  376.     set msgs {}
  377.     for {set i 1} {$i <= $cnt} {incr i} {
  378.         set subject {}
  379.         if {![regexp -nocase {From: (.*)} [mailGetField from $folder $i] dummy from]} {
  380.             error "No from field!"
  381.         }
  382.         regexp {Subject: (.*)} [mailGetField subject $folder $i] dummy subject
  383.         lappend msgs [list $from $subject]
  384.     }
  385.     return $msgs
  386. }    
  387.  
  388.  
  389. proc eudoraCc {} {
  390.     if {![catch {set res [search -s -f 1 -r 1 -i 1 {cc:.*} 0]}]} {
  391.         goto [lindex $res 0]
  392.         endOfLine
  393.     } else {
  394.         beginningOfBuffer
  395.         nextLine
  396.         insertText "Cc: \r"
  397.         backwardChar
  398.     }
  399. }
  400.  
  401.  
  402. proc eudoraBcc {} {
  403.     if {![catch {set res [search -s -f 1 -r 1 -i 1 {bcc:.*} 0]}]} {
  404.         goto [lindex $res 0]
  405.         endOfLine
  406.     } else {
  407.         beginningOfBuffer
  408.         nextLine
  409.         insertText "Bcc: \r"
  410.         backwardChar
  411.     }
  412. }
  413.  
  414.  
  415. proc mailFlushOut {} {
  416.     global MailmodeVars
  417.     message "Telling Eudora to flush messages…"
  418.  
  419.     AEBuild 'CSOm' CSOm eCon eSen bool(«01») eChk bool(«00»)
  420.     message ""
  421. }
  422.  
  423.  
  424. proc mailCheck {} {
  425.     global MailmodeVars mailflushOnCheck
  426.     message "Told Eudora to check for new mail…"
  427.  
  428.     AEBuild 'CSOm' CSOm eCon eSen bool(«0$mailflushOnCheck») eChk bool(«01»)
  429. }
  430.  
  431.  
  432. proc mailReplymsg {{toall 0}} {
  433.     global inboxMembers
  434.  
  435.     set prefix "> "
  436.     set res [search -s -f 1 -r 1 {^>==} 0]
  437.     set header [getText 0 [lindex $res 0]]
  438.     
  439.     set from [mailGetFrom]
  440.     if {![regexp {Subject: ([^\r]*)} $header dummy subject]} {set subject ""}
  441.     set body [getText [expr [lindex $res 1] + 1] [maxPos]]
  442.  
  443.     regsub -all "\r" $body "\r$prefix" body
  444.     mailNewMsg $from "" "" "Re: $subject" "\r$prefix$body\r"
  445. }
  446.  
  447. proc transferProc {menu item} {
  448.     if {$item == "Move To Trash"} {
  449.         mailTrashmsg
  450.     } elseif {$item == "Move To Mailbox"} {
  451.         moveToMailbox
  452.     } else {
  453.         doFolderMove $item
  454.     }
  455. }
  456.  
  457.  
  458. proc mailTrashmsg {} {
  459.     global trashName
  460.     doFolderMove $trashName
  461. }
  462.  
  463. proc doFolderMove {toFolder} {
  464.     # Is this a summary or msg window?
  465.     if {[regexp "MAILBOX" [win::CurrentTail]]} {
  466.         if {![regexp {∞(.*)∞([0-9]+)} [getText [getPos] [nextLineStart [getPos]]] dummy folder orig]} {
  467.             beep
  468.             return
  469.         }
  470.         if {$toFolder == $folder} return
  471.         global trashedMsgs$folder
  472.  
  473.         set deleted 0
  474.         for {set i 1} {$i < $orig} {incr i} {
  475.             if {[lsearch [set trashedMsgs$folder] $i] >= 0} {
  476.                 incr deleted
  477.             }
  478.         }
  479.         set number [expr $orig - $deleted]
  480.         set summary 1
  481.     } else {
  482.         set pos [lindex [search -f 1 -r 1 {^Msg} 0] 0]
  483.         set text [getText $pos [nextLineStart $pos]]
  484.         regexp {"([^"]+)" \(([0-9]+)\).*"([^"]+)"} $text dummy number orig folder
  485.         if {$toFolder == $folder} return
  486.         set summary 0
  487.  
  488.         global trashedMsgs$folder
  489.     }
  490.     
  491.     message "Moving msg $number ($orig) of folder '$folder' to '$toFolder'"
  492.     moveMsg $number $folder $toFolder
  493.     if {!$summary} killWindow
  494.  
  495.     lappend trashedMsgs$folder $orig
  496.     
  497.     # Find summary info and delete it
  498.     set win [win::CurrentTail]
  499.     if {[regexp "MAILBOX" $win]} {
  500.         setWinInfo read-only 0
  501.     
  502.         set inds [search -f 1 -r 1 "∞$folder∞$orig\$" 0]
  503.         set pos [lindex $inds 0]
  504.         deleteText [lineStart $pos] [nextLineStart $pos]
  505.     
  506.         if {[string length [search -n -f 1 -r 0 {∞} 0]]} {
  507.             setWinInfo dirty 0
  508.             setWinInfo read-only 1
  509.     
  510.             nextLine
  511.             upBrowse
  512.         } else {
  513.             setWinInfo dirty 0
  514.             killWindow
  515.         }
  516.     }
  517. }
  518.  
  519.     
  520. proc mailGetFrom {} {
  521.     set res [search -s -f 1 -r 1 {>==} 0]
  522.     set header [getText 0 [lindex $res 0]]
  523.     if {[regexp {From: ([^\r]*)} $header dummy from]} {
  524.         return [mailAddr $from]
  525.     }
  526.     error "No from line"
  527. }
  528.  
  529.     
  530.  
  531. proc mailSendCreatedMsg {} {
  532.     global MailmodeVars mailimmediateSend
  533.     
  534.     set name [checkMailPath]
  535.     set res [search -s -f 1 -r 0 {>==text follows this line==<} 0]
  536.     set header [getText 0 [lindex $res 0]]
  537.     
  538.     if {![regexp {To: ([^\r]*)} $header dummy to]} {set to ""}
  539.     if {![regexp {[Cc]+: ([^\r]*)} $header dummy cc]} {set cc ""}
  540.     if {![regexp {Subject: ([^\r]*)} $header dummy subject]} {set subject ""}
  541.  
  542.     set body [getText [expr [lindex $res 1] + 1] [maxPos]]
  543.     
  544.     mailCreateMsg
  545.     mailSetField to $to
  546.     mailSetField cc $cc
  547.     mailSetField subject $subject
  548.     mailSetField "" $body
  549.     
  550.     if {$MailmodeVars(tossOnQueue)} {
  551.         setWinInfo dirty 0
  552.         killWindow
  553.     }
  554.  
  555.     mailQueueLast
  556.  
  557.     if {$MailmodeVars(switchOnQueue)} {
  558.         switchTo $name
  559.     }
  560.  
  561.     if {$mailimmediateSend} {
  562.         mailFlushOut
  563.     } else {
  564.         message "Message queued…"
  565.     }
  566. }
  567.  
  568.     
  569. proc mailNewMsg {{to ""} {cc ""} {bcc ""} {subject ""} {body ""}} {
  570.     new -n "New Mail" -m Mail
  571.  
  572.     insertText "To: $to\rSubject: $subject\r>==text follows this line==<\r$body"
  573.     setWinInfo dirty 0
  574.     goto 0
  575.     refresh
  576.     mailTab
  577. }
  578.  
  579.  
  580. proc mailTab {} {
  581.     global mailKeywords
  582.     if {[catch {search -s -f 1 -r 1 -i 1 "([join $mailKeywords {|}]|^>)" [getPos]} res]} {
  583.         insertText "\t"
  584.         return
  585.     }
  586.     if {[lookAt [lindex $res 0]] == ">"} {
  587.         select [nextLineStart [lindex $res 1]] [maxPos]
  588.     } else {
  589.         goto [expr [lindex $res 1] + 1]
  590.         endLineSelect
  591.     }
  592. }
  593.  
  594. proc mailOpen {folder i originalNum} {
  595.     global tileLeft tileTop tileHeight trashedMsgs$folder defWidth
  596.     
  597.     set from [mailGetField From $folder $i]
  598.     set to [mailGetField To $folder $i]
  599.     set subject [mailGetField Subject $folder $i]
  600.     set sender [mailGetField Sender $folder $i]
  601.     set date [mailGetField Date $folder $i]
  602.     set cc [mailGetField cc $folder $i]
  603.     set contents [mailGetField "" $folder $i]
  604.     
  605. #===============================================================================
  606.     global tileHeight tileTop tileLeft errorHeight errorDisp defWidth
  607.     set top $tileTop
  608.     set geo [getGeometry]
  609.     if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $defWidth) || ([lindex $geo 3] != $errorHeight) } {
  610.         moveWin $tileLeft $top
  611.         sizeWin $defWidth $errorHeight
  612.     }
  613.     set mar 28
  614.     incr top [expr $errorHeight + $mar]
  615. #===============================================================================
  616.     set name [new -n "MAIL" -g $tileLeft $top $defWidth [expr $errorDisp - 5] -m Mail]
  617.  
  618.     set text {}
  619.     if {[string length $subject]} {append text "$subject\r"}
  620.     if {[string length $to]} {append text "$to\r"}
  621.     if {[string length $from]} {append text "$from\r"}
  622.     if {[string length $date]} {append text "$date\r"}
  623.     if {[string length $cc]} {append text "$cc\r"}
  624.     if {[string length $sender]} {append text "$sender\r"}
  625.     append text "Msg \"$i\" ($originalNum) of mailbox \"$folder\"     Reply     Trash\r"
  626.     insertText "${text}>===============================================================================
  627. $contents
  628. "
  629.     goto 0
  630.     goto [lindex [search -f 1 -m 0 -r 1 {^Msg "} 0] 0]
  631.     set pos [getPos]
  632.     regexp -indices {([0-9]+).*mailbox "(.+)".*(Reply).*(Trash)} [getText $pos [nextLineStart $pos]] dummy num fold rep tra
  633.     colorSelectPos [expr $pos + [lindex $num 0]] [expr 1 + $pos + [lindex $num 1]] bold 12
  634.     colorSelectPos [expr $pos + [lindex $fold 0]] [expr 1 +$pos + [lindex $fold 1]] bold 12
  635.     hyperSelectPos [expr $pos + [lindex $rep 0]] [expr 1 +$pos + [lindex $rep 1]] "mailReplymsg"
  636.     hyperSelectPos [expr $pos + [lindex $tra 0]] [expr 1 +$pos + [lindex $tra 1]] "mailTrashmsg"
  637.  
  638.     goto 0
  639.     setWinInfo dirty 0
  640.     setWinInfo read-only 1
  641.     refresh
  642. }
  643.  
  644. proc colorSelectPos {from to ind ind2} {
  645.     insertColorEscape $from $ind
  646.     insertColorEscape $to $ind2
  647. }
  648.  
  649. proc hyperSelectPos {from to text} {
  650.     if {$from == $to} {
  651.         beep
  652.         return
  653.     }
  654.     insertColorEscape $from 3
  655.     insertColorEscape $from 15 $text
  656.     insertColorEscape $to 12
  657.     insertColorEscape $to 0
  658. }
  659.  
  660. proc mailFixMenus {} {
  661.     global eudoraMenu
  662.     
  663.     set ins {}
  664.     set outs {}
  665.     
  666.     set cnt [mailCountMsgs in]
  667.     for {set i 1} {$i <= $cnt} {incr i} {
  668.         lappend ins [mailGetField from in $i]
  669.     }
  670.     menu -n in {}
  671.     foreach item $ins {
  672.         addMenuItem -l "" in $item
  673.     }
  674.     
  675.     set cnt [mailCountMsgs out]
  676.     for {set i 1} {$i <= $cnt} {incr i} {
  677.         lappend outs [mailGetField from out $i]
  678.     }
  679.     menu -n out {}
  680.     foreach item $outs {
  681.         addMenuItem -l "" out $item
  682.     }
  683. }
  684.  
  685.  
  686. # make message at end of mailbox "out" of mail folder ""
  687. proc mailCreateMsg {} {
  688.     createThingAtEnd 'CSOm' [mailboxByName Out] euMS
  689. }
  690.  
  691.  
  692. # Move msg w/ specified index between folders, including to Trash.
  693. proc moveMsg {msg infolder outfolder} {
  694.     AEBuild -r 'CSOm' core move {----} "obj \{form:indx, want:type(euMS), seld:$msg, from:obj \{form:name, want:type(euMB), seld:“$infolder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}\}" {insh} "insl\{kobj:obj \{form:name, want:type(euMB), seld:“$outfolder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}, kpos:end \}"
  695. }
  696.  
  697.  
  698. # set field "fld" of message 0 to "to"
  699. proc mailSetField {fld to} {
  700.     AEBuild -r 'CSOm' core setd {----} "obj \{form:name, want:type(euFd), seld:“$fld”, from:obj \{form:indx, want:type(euMS), seld:1, from:'null'()\}\}" data "“$to”"
  701. }
  702.  
  703. proc mailGetField {field folder msg} {
  704.     if {[catch {getObjectData 'CSOm' euFd $field [eudoraMessage $msg $folder]} res]} {
  705.         return ""
  706.     } else {
  707.         return $res
  708.     }
  709. }
  710.  
  711. # obj {want:type('prop'), from:obj {form:indx, want:type(euMS), seld:$msg, from:obj {form:name, want:type(euMB), seld:“$folder”, from:obj {form:name, want:type(euMF), seld:'TEXT'(), from:'null'()}}}, form:'prop', seld:type('euST')}
  712.  
  713. proc mailMsgStatus {folder msg} {
  714.     if {[catch {AEBuild -r 'CSOm' core getd {----} "obj \{want:type('prop'), from:obj \{form:indx, want:type(euMS), seld:$msg, from:obj \{form:name, want:type(euMB), seld:“$folder”, from:obj \{form:name, want:type(euMF), seld:'TEXT'(), from:'null'()\}\}\}, form:'prop', seld:type('euST')\}"} text]} {
  715.         return ""
  716.     }
  717.     set from [string first "“" $text]
  718.     set to [string first "”" $text]
  719.     return [string range $text [expr $from + 1] [expr $to - 1]]
  720. }
  721.  
  722. proc mailQueueLast {} {
  723.     AEBuild -r 'CSOm' CSOm eQue ---- {obj {form:indx, want:type(euMS), seld:1, from:'null'()}}
  724. }
  725.  
  726. # CSOm\eAtc{'----':obj {form:indx, want:type(euMS), seld:1, from:'null'()}, eDcl:[fss («486172643A4465736B746F7020466F6C6465723A62756773»)]}
  727. proc mailAttachmentDoesntWork {name} {
  728.     AEBuild -r 'CSOm' CSOm eAtc ---- {obj {form:indx, want:type(euMS), seld:1, from:'null'()}} eDcl [makeAlis $name]
  729. }
  730.  
  731. # core\setd{'----':obj {form:prop, want:type(prop), seld:type(euPY), from:obj {form:indx, want:type(euMS), seld:1, from:'null'()}}, data:1}
  732. proc mailSetNumberProperty {prop to} {
  733.     AEBuild -r 'CSOm' core setd ---- "obj \{form:prop, want:type(prop), seld:type($prop), from:obj \{form:indx, want:type(euMS), seld:1, from:'null'()\}\}" data $to
  734. }    
  735.  
  736.  
  737. proc mailCountMsgs {mbox} {
  738.     return [countObjects 'CSOm' [mailboxByName "$mbox"]  euMS]
  739. }
  740.  
  741. proc mailCountMailboxes {} {
  742.      return [countObjects 'CSOm' [eudoraFolder] euMB]
  743. }
  744.     
  745.  
  746. proc updateMailboxLists {} {
  747.     set num [mailCountMailboxes]
  748.     for {set i 1} {$i <= $num} {incr i} {
  749.         set name [file tail [mailboxPathIndex $i]]
  750.         message $name
  751.         lappend boxes $name
  752.     }
  753.     
  754.     global eudoraBoxes modifiedVars
  755.     lappend modifiedVars eudoraBoxes
  756.     set eudoraBoxes $boxes
  757.     menu -n open -p mailBoxProc -m $eudoraBoxes
  758.     menu -n moveTo -p transferProc -m $eudoraBoxes
  759.     message "done."
  760. }
  761.  
  762.  
  763. #===============================================================================
  764.  
  765. eventHandler CSOm eNot "eudoraHandler"
  766.  
  767. # a sample 'msgs': obj {want:type(euMS), from:obj {want:type(euMB), from:obj {want:type(euMF), from:'null'(), form:name, seld:'TEXT'()}, form:name, seld:“In”}, form:indx, seld:18}, obj {want:type(euMS), from:obj {want:type(euMB), from:obj {want:type(euMF), from:'null'(), form:name, seld:'TEXT'()}, form:name, seld:“In”}, form:indx, seld:19}
  768. proc eudoraHandler {it} {
  769.     global blah mailalertOnIncoming
  770.     message ""
  771.     if {[regexp {eWHp:wArv.*\[(obj.*)\], &repq} $it dum1 msgs]} {
  772.         set ids [getMsgIDs $msgs]
  773.         if {$mailalertOnIncoming} {
  774.             mailBrowser In $ids
  775.         }
  776.     } else {
  777.         message "No mail"
  778.     }
  779. }
  780.  
  781.  
  782. proc mailBrowser {folder ids} {
  783.     global inboxMembers ALPHA
  784.     global tileLeft tileTop defWidth tileHeight errorHeight
  785.  
  786.     checkMailPath
  787.     switchTo $ALPHA
  788.  
  789.     global trashedMsgs$folder
  790.     set trashedMsgs$folder {}
  791.     
  792.     set inboxMembers {}
  793.     set text {}
  794.  
  795.     foreach id $ids {
  796.         regexp {From: (.*)} [mailGetField from $folder $id] dummy from
  797.         set from [mailAddr $from]
  798.         set subject {}
  799.         regexp {Subject: (.*)} [mailGetField subject $folder $id] dummy subject
  800.         set tag {}
  801.         while {[lsearch $inboxMembers $from$tag] >= 0} {
  802.             if {![string length $tag]} {
  803.                 set tag { <2>}
  804.             } else {
  805.                 regexp {[0-9]+} $tag tag
  806.                 set tag " <[expr $tag + 1]>"
  807.             }
  808.         }
  809.         append text [format "%-40s : %s\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞In∞$id\r" "$from$tag" $subject]
  810.         lappend inboxMembers $from$tag
  811.     }
  812.     if {![string length $text]} {
  813.         alertnote "No messages!"
  814.         return
  815.     }
  816.     
  817.     if {[set ind [lsearch [winNames] "*Incoming MAILBOX*"]] >= 0} {
  818.         bringToFront [lindex [winNames] $ind]
  819.         setWinInfo read-only 0
  820.         endOfBuffer
  821.         insertText $text
  822.     } else {
  823.         killMailboxWindow
  824.         new -n "* Incoming MAILBOX *" -g $tileLeft $tileTop $defWidth $errorHeight -m Brws
  825.  
  826.         insertText "(<cr> to go to message)\r-----\r$text"
  827.     }
  828.     select [nextLineStart [nextLineStart 0]] [nextLineStart [nextLineStart [nextLineStart 0]]]
  829.     setWinInfo dirty 0
  830.     setWinInfo read-only 1
  831.     message ""
  832. }
  833.  
  834.  
  835. proc getMsgIDs {text} {
  836.     if {[regexp -indices {seld:([0-9]+)} $text dummy ind]} {
  837.         return [concat [string range $text [lindex $ind 0] [lindex $ind 1]] [getMsgIDs [string range $text [lindex $ind 1] end]]]
  838.     }
  839. }
  840.  
  841. proc startNotifying {} {
  842.     global HOME ALPHA quitHooks
  843.     
  844.     AEBuild 'CSOm' CSOm nIns ---- [makeAlis "$HOME:$ALPHA"]
  845. #     lappend quitHooks stopNotifying
  846. }
  847.  
  848. proc stopNotifying {} {
  849.     global HOME ALPHA
  850.     
  851.     AEBuild 'CSOm' CSOm nRem ---- [makeAlis "$HOME:$ALPHA"]
  852. }
  853.